package xhe.lib.base;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;

import org.springframework.util.StringUtils;

import sun.misc.BASE64Encoder;

/**
 * <b> 工具类: </b> Token操作类
 * 
 * @author xhe
 * @version V1.0.0.0
 * @version --2019年11月25日
 */
public class Token {

	private static HashMap<String, TokenEntity> TokenList = new HashMap<String, TokenEntity>();
	private static final long EXPIRE_TIME = 15 * 60 * 1000;
	private static final String TOKEN_SECRET = "#h@E$r&X^%u?*";

	/**
	 * <b> 方法: </b> 根据用户名密码生成Token
	 * 
	 * @author xhe
	 * @param userName 用户名
	 * @param passWord 密码
	 * @return String Token加密字符串
	 * @version V1.0.0.0
	 * @version --2019年11月25日
	 * @version --新增方法
	 */
	public static String createToken(String userName, String passWord) {
		String strKey = "";
		String strToken = "";
		String strSecretKey = userName + TOKEN_SECRET + passWord;
		try {
			BASE64Encoder encoder = new BASE64Encoder();

			MessageDigest mdKey = MessageDigest.getInstance("MD5");
			byte byKey[] = mdKey.digest(strSecretKey.getBytes());
			strKey = encoder.encode(byKey).replace("\\", "").replace("/", "").replace("|", "").replace("%", "")
					.replace(".", "").replace("+", "").replace("\n", "").replace("\r", "");

			MessageDigest mdToken = MessageDigest.getInstance("SHA-512");
			byte byToken[] = mdToken.digest(strSecretKey.getBytes());
			strToken = encoder.encode(byToken).replace("\\", "").replace("/", "").replace("|", "").replace("%", "")
					.replace(".", "").replace("+", "").replace("\n", "").replace("\r", "");

			System.out.println(strKey);
			System.out.println(strToken);

			if (!TokenList.containsKey(strKey)) {
				TokenEntity oTokenEntity = new TokenEntity();
				oTokenEntity.setKey(strKey);
				oTokenEntity.setValue(strToken);
				oTokenEntity.setTime(new Date());

				TokenList.put(strKey, oTokenEntity);
			} else {
				TokenList.get(strKey).setValue(strToken);
				TokenList.get(strKey).setTime(new Date());
			}
			System.out.println(TokenList);
		} catch (NoSuchAlgorithmException e) {

			e.printStackTrace();
		}

		return strKey + "|" + strToken;
	}

	/**
	 * <b> 方法: </b> 移除Token
	 * 
	 * @author xhe
	 * @param tokenKey Token的Key
	 * @version V1.0.0.0
	 * @version --2019年11月25日
	 * @version --新增方法
	 */
	public static void removeToken(String tokenKey) {
		if (TokenList.containsKey(tokenKey)) {
			TokenList.remove(tokenKey);
		}
	}

	/**
	 * <b> 方法: </b> 验证Token
	 * 
	 * @author xhe
	 * @param tokenKey         服务器端Token
	 * @param tokenClientValue 客户端Token
	 * @return boolean 验证的结果
	 * @version V1.0.0.0
	 * @version --2019年11月25日
	 * @version --新增方法
	 */
	public static boolean judgeToken(String tokenKey, String tokenClientValue) {

		if (StringUtils.isEmpty(tokenClientValue)) {
			return false;
		}
		if (!TokenList.containsKey(tokenKey)) {
			return false;
		} else {
			String tokenServiceValue = TokenList.get(tokenKey).getValue();

			if (StringUtils.isEmpty(tokenServiceValue)) {
				return false;
			}

			if (!tokenServiceValue.equals(tokenClientValue)) {
				return false;
			} else {
				Date tokenTime = TokenList.get(tokenKey).getTime();

				if (System.currentTimeMillis() > (tokenTime.getTime() + EXPIRE_TIME)) {
					return false;
				} else {
					TokenList.get(tokenKey).setTime(new Date());
				}
			}
		}
		return true;
	}

	/**
	 * <b> 方法: </b> 根据用户名和密码获取Token
	 * 
	 * @author xhe
	 * @param userName 用户名
	 * @param passWord 密码
	 * @return String Token加密字符串
	 * @version V1.0.0.0
	 * @version --2019年11月25日
	 * @version --新增方法
	 */
	public static String getToken(String userName, String passWord) {
		String strToken = createToken(userName, passWord);
		// System.out.println("Token:" + strToken);
		return strToken;
	}

}

class TokenEntity {
	String Key = "";
	String Value = "";
	Date Time = new Date();

	// 属性：Key
	public String getKey() {
		return this.Key;
	}

	// 设置：Key
	public void setKey(String key) {
		this.Key = key;
	}

	// 属性：Value
	public String getValue() {
		return this.Value;
	}

	// 设置：Value
	public void setValue(String value) {
		this.Value = value;
	}

	// 属性：Time
	public Date getTime() {
		return this.Time;
	}

	// 设置：Time
	public void setTime(Date date) {
		this.Time = date;
	}
}
